#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <vector>

// 1. 报文和报文之间，我们采用特殊字符来进行解决粘包问题
// 2. 获取一个一个独立完整的报文，序列和反序列化 -- 自定义
// 100+19X100+19X100+19
#define SEP "X"
#define SEP_LEN strlen(SEP)

// 要把传入进来的缓冲区进行切分，要求：
// 1. buffer被切走的，也同时要从buffer中移除
// 2. 可能会存在多个报文，多个报文依次放入out
void SpliteMessage(std::string &buffer, std::vector<std::string> *out) // 分割报文
{   // buffer: 输入输出型参数，out: 输出型参数
    while (true)
    {
        auto pos = buffer.find(SEP); // 在缓冲区里找分隔符
        if (std::string::npos == pos) // 找不到就break
            break;
        std::string message = buffer.substr(0, pos); // 提取子串：前闭后开区间
        buffer.erase(0, pos + SEP_LEN); // 移除子串和衡娥福
        out->push_back(message); // push_back完整的子串
        // std::cout << "debug: " << message << " : " << buffer << std::endl;
        // sleep(1);
    }
}

// 自己手写序列反序列化
#define SPACE " "
#define SPACE_LEN strlen(SPACE)

std::string Encode(std::string& s)
{
    return s + SEP;
}

class Request
{
public:
    std::string Serialize()
    {
        std::string str;
        str = std::to_string(_x);
        str += SPACE;
        str += _op;
        str += SPACE;
        str += std::to_string(_y);
        return str;
    }
    bool Deserialized(const std::string& str) // 1 + 1
    {
        std::size_t left = str.find(SPACE);
        if (left == std::string::npos)
            return false;
        std::size_t right = str.rfind(SPACE);
        if (right == std::string::npos)
            return false;
        _x = atoi(str.substr(0, left).c_str());
        _y = atoi(str.substr(right + SPACE_LEN).c_str());
        if (left + SPACE_LEN > str.size())
            return false;
        else
            _op = str[left + SPACE_LEN];
        return true;
    }

public:
    Request()
    {}
    Request(int x, int y, char op) 
        : _x(x), _y(y), _op(op)
    {}
    ~Request() 
    {}
public:
    int _x;
    int _y;
    char _op; // '+' '-' '*' '/' '%'
};

class Response
{
public:
    std::string Serialize() // "code_ result_"
    {

        std::string s;
        s = std::to_string(_code);
        s += SPACE;
        s += std::to_string(_result);

        return s;
    }
    bool Deserialized(const std::string& s)
    {
        std::size_t pos = s.find(SPACE);
        if (pos == std::string::npos)
            return false;
        _code = atoi(s.substr(0, pos).c_str());
        _result = atoi(s.substr(pos + SPACE_LEN).c_str());
        return true;
    }
public:
    Response()
    {}
    Response(int result, int code) 
        : _result(result), _code(code)
    {}
    ~Response()
    {}
public:
    int _result; // 计算结果
    int _code;   // 计算结果的状态码
};